package com.xy.biz.xd.service.impl;

import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.client.DocumentCodeRuleClient;
import com.xy.biz.fd.domain.DocumentPermissions;
import com.xy.biz.fd.domain.enums.DocumentDefaultRepositoryEnum;
import com.xy.biz.fd.domain.req.document.SaveDocumentRequest;
import com.xy.biz.fd.domain.req.documentCode.GetDocumentByCodeRequest;
import com.xy.biz.fd.domain.resp.GetDocumentResponse;
import com.xy.biz.fd.domain.resp.GetSourceFlowUserAndGroupResponse;
import com.xy.biz.fd.domain.resp.GetUserGroupResponse;
import com.xy.biz.fd.domain.resp.GetUserResponse;
import com.xy.biz.fd.domain.utils.DocumentPropertyUtils;
import com.xy.biz.mc.client.MessagePushClient;
import com.xy.biz.mc.domain.Message;
import com.xy.biz.mc.domain.consts.MessageTypeConstant;
import com.xy.biz.mc.domain.req.MessagePushRequest;
import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.client.UserGroupClient;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.uc.domain.req.ListUserGroupByIdsRequest;
import com.xy.biz.xd.domain.bo.*;
import com.xy.biz.xd.domain.converter.DocumentFlowConverter;
import com.xy.biz.xd.domain.converter.DocumentFlowNewAndModifyConverter;
import com.xy.biz.xd.domain.enums.DocumentFlowBatchTypeEnum;
import com.xy.biz.xd.domain.enums.DocumentReleaseStatusEnum;
import com.xy.biz.xd.domain.query.DocumentFlowHandleQuery;
import com.xy.biz.xd.domain.query.DocumentFlowNewAndModifyQuery;
import com.xy.biz.xd.domain.query.DocumentFlowQuery;
import com.xy.biz.xd.domain.req.HandleDocumentFlowRequest;
import com.xy.biz.xd.domain.req.ReleaseDocumentFlowNewAndModifyRequest;
import com.xy.biz.xd.domain.req.ReviewDocumentFlowRequest;
import com.xy.biz.xd.domain.resp.GetDocumentFlowHandleResponse;
import com.xy.biz.xd.domain.resp.ListDocumentFlowBrorowAndPrintAndDropResponse;
import com.xy.biz.xd.domain.resp.ListDocumentFlowNewAndModifyResponse;
import com.xy.biz.xd.manager.DocumentFlowHandleManager;
import com.xy.biz.xd.manager.DocumentFlowManager;
import com.xy.biz.xd.manager.DocumentFlowNewAndModifyManager;
import com.xy.biz.xd.manager.DocumentReleaseManager;
import com.xy.biz.xd.service.DocumentFlowBorrowAndPrintAndDropService;
import com.xy.biz.xd.service.DocumentFlowHandleService;
import com.xy.biz.xd.service.DocumentReleaseService;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.tuples.Triple;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.gid.service.GidService;
import com.xy.tool.json.JsonUtils;
import com.xy.tool.util.BeanUtilsEx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.xy.biz.fd.domain.DocumentPermissions.PREVIEW;
import static com.xy.biz.fd.domain.DocumentPermissions.VISIBLE;
import static com.xy.biz.xd.domain.bo.DocumentFlowConstants.*;
import static com.xy.biz.xd.domain.bo.DocumentReleaseBO.*;
import static java.util.stream.Collectors.toList;

public abstract class AbstractDocumentFlowBorrowAndPrintAndDropServiceImpl implements DocumentFlowBorrowAndPrintAndDropService {

    @Autowired
    private DocumentFlowManager documentFlowManager;
    @Autowired
    private DocumentFlowServiceSupport documentFlowServiceSupport;
    @Autowired
    private DocumentFlowHandleManager documentFlowHandleManager;
    @Autowired
    private DocumentCodeRuleClient documentCodeRuleClient;
    @Autowired
    private DocumentClient documentClient;
    @Autowired
    private DocumentReleaseManager documentReleaseManager;
    @Autowired
    private UserGroupClient userGroupClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private GidService gidService;
    @Autowired
    private MessagePushClient messagePushClient;

    protected abstract String getType();

    @Transactional
    @Override
    public Result<?> contentAuditDocumentFlow(HandleDocumentFlowRequest request) {
        LocalDateTime now = LocalDateTime.now();
        DocumentFlowBO documentFlowBO = documentFlowManager.getDocumentFlow(request.getDocumentFlowId());
        if (Objects.equals(request.getResult(), HANDLE_RESULT_ACCEPT)) {
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(documentFlowBO, UserContextHolder.getUserId(), PHASE_CONTENT_AUDIT, HANDLE_RESULT_ACCEPT, request.getOpinion());
            //审批流程处理人存储
            documentFlowHandleManager.saveAllDocumentFlowHandle(Arrays.asList(documentFlowHandleBO));
            documentFlowBO.setPhase(PHASE_APPROVAL);
//            //评审人数量
//            documentFlowBO.setReviewerNum(request.getReviewUserIdList().size());
            //流程推动至下一节点
            documentFlowServiceSupport.gotoNextTask(documentFlowBO, request.getNextHandleUserId(), HANDLE_RESULT_ACCEPT);
        } else if (Objects.equals(request.getResult(), HANDLE_RESULT_REJECT)) {
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(documentFlowBO, UserContextHolder.getUserId(), PHASE_CONTENT_AUDIT, HANDLE_RESULT_FINISH_FLOW, request.getOpinion());
            documentFlowHandleManager.saveAllDocumentFlowHandle(Arrays.asList(documentFlowHandleBO));
            documentFlowBO.setPhase(PHASE_REJECT);
            documentFlowServiceSupport.gotoNextTask(documentFlowBO, null, HANDLE_RESULT_END);
        }
        documentFlowBO.setUpdateTime(now);
        int row = documentFlowManager.updateDocumentFlow(documentFlowBO);
        if (row > 0) {
            //发送消息
            //通过
            if (Objects.equals(request.getResult(), HANDLE_RESULT_ACCEPT)) {
                Message message = Message.builder()
                        .type(MessageTypeConstant.TYPE_FLOW)
                        .data(1)
                        .remark(getType() + "流程-审批")
                        .path(MessageTypeConstant.FLOW_LIST)
                        .build();
                sendMessage(message, request.getNextHandleUserId());
            } else {//拒绝通过
                //获取申请用户id  查找申请人员
                Long applyUserId = getApplyUserId(request.getDocumentFlowId(), PHASE_APPLY);
                //发送消息
                //定义消息内容
                Message message = Message.builder()
                        .type(MessageTypeConstant.TYPE_FLOW)
                        .data(0)
                        .remark(getType() + "流程-文件审核不通过")
                        .path(MessageTypeConstant.FLOW_LIST)
                        .build();
                sendMessage(message, applyUserId);
            }
        }
        return Result.success();
    }

//    @Override
//    public Result<?> reviewDocumentFlow(ReviewDocumentFlowRequest request) {
//        LocalDateTime now = LocalDateTime.now();
//
//        DocumentFlowBO documentFlowBO = documentFlowManager.getDocumentFlow(request.getDocumentFlowId());
//
//        Result<List<GetDocumentFlowHandleResponse>> listResult = documentFlowHandleService.listDocumentFlowHandleByDocumentCode(GetDocumentByCodeRequest.builder()
//                .code(documentFlowBO.getDocumentCode())
//                .phase(PHASE_CONTENT_AUDIT)
//                .build());
//        if (!listResult.wasSuccess()) {
//            return Result.ofBadRequest("源文件信息获取失败");
//        }
//        GetDocumentFlowHandleResponse getDocumentFlowHandleResponse = listResult.getData().get(0);
//        //获取审批人
//        Long handleUserId = getDocumentFlowHandleResponse.getHandleUserId();
//
//        DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(documentFlowBO, UserContextHolder.getUserId(), PHASE_REVIEW, HANDLE_RESULT_ACCEPT, request.getOpinion());
//        documentFlowHandleManager.saveAllDocumentFlowHandle(Arrays.asList(documentFlowHandleBO));
//        documentFlowServiceSupport.gotoNextTask(documentFlowBO, handleUserId, HANDLE_RESULT_ACCEPT);
//        //获取已评审人员数量
//        int reviewedCount = documentFlowServiceSupport.getHandleCountForPhaseAndResult(documentFlowBO, PHASE_REVIEW, HANDLE_RESULT_ACCEPT);
//
//        if (reviewedCount == documentFlowBO.getReviewerNum()) {
//            //设置下一节点
//            documentFlowBO.setPhase(PHASE_RELEASE);
//        }
//        documentFlowBO.setUpdateTime(now);
//        int row = documentFlowManager.updateDocumentFlow(documentFlowBO);
//
//        //做信息发送
//        if (row > 0 && reviewedCount == documentFlowBO.getReviewerNum()) {
//            //发送消息
//            //定义消息内容
//            Message message = Message.builder()
//                    .type(MessageTypeConstant.TYPE_FLOW)
//                    .data(1)
//                    .remark(getType() + "流程-发行")
//                    .path(MessageTypeConstant.FLOW_LIST)
//                    .build();
//
//            sendMessage(message, handleUserId);
//        }
//        return Result.success();
//    }

    @Override
    public Result<GetSourceFlowUserAndGroupResponse> getSourceFlowUserAndGroup(GetDocumentByCodeRequest request) {
        List<DocumentReleaseBO> documentReleaseBOS = documentReleaseManager.listDocumentReleaseByDocumentCode(request.getCode());
        if (CollectionUtils.isEmpty(documentReleaseBOS)) {
            return Result.success();
        }
        List<GetUserGroupResponse> userGroupResponses = new ArrayList<>();
        List<GetUserResponse> userResponses = new ArrayList<>();
        Set<Long> groupIds = documentReleaseBOS.stream().filter(d -> d.getReceiveType() == 1).map(DocumentReleaseBO::getReceiveId).collect(Collectors.toSet());
        Set<Long> userIds = documentReleaseBOS.stream().filter(d -> d.getReceiveType() == 0).map(DocumentReleaseBO::getReceiveId).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(groupIds)) {
            groupIds.stream().peek(g -> {
                GetUserGroupResponse build = GetUserGroupResponse.builder().id(g).build();
                userGroupResponses.add(build);
            }).collect(Collectors.toSet());
            userGroupClient.buildByUserGroup(userGroupResponses,
                    userGroupResponses.stream().map(GetUserGroupResponse::getId).collect(Collectors.toSet()),
                    GetUserGroupResponse::getId,
                    (resp, userGroupDTO) -> resp.setLabel(userGroupDTO.getUserGroupName()));

        }
        if (!CollectionUtils.isEmpty(userIds)) {
            userIds.stream().peek(g -> {
                GetUserResponse build = GetUserResponse.builder().id(g).build();
                userResponses.add(build);
            }).collect(Collectors.toSet());
            userClient.buildByUser(userResponses,
                    userResponses.stream().map(GetUserResponse::getId).collect(Collectors.toSet()),
                    GetUserResponse::getId,
                    (resp, userDTO) -> resp.setLabel(userDTO.getUserName()));
        }
        return Result.success(GetSourceFlowUserAndGroupResponse.builder().groups(userGroupResponses).users(userResponses).build());
    }

    @Transactional
    @Override
    public Result<?> approvalDocumentFlow(HandleDocumentFlowRequest request) {
        LocalDateTime now = LocalDateTime.now();
        DocumentFlowBO documentFlowBO = documentFlowManager.getDocumentFlow(request.getDocumentFlowId());
        if (Objects.isNull(documentFlowBO)) {
            return Result.ofNotFound(String.valueOf(request.getDocumentFlowId()));
        }
        if (Objects.equals(request.getResult(), HANDLE_RESULT_ACCEPT)) {
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(documentFlowBO, UserContextHolder.getUserId(), PHASE_APPROVAL, HANDLE_RESULT_ACCEPT, request.getOpinion());
            documentFlowHandleManager.saveAllDocumentFlowHandle(Arrays.asList(documentFlowHandleBO));
            documentFlowBO.setPhase(PHASE_RELEASE);
            documentFlowServiceSupport.gotoNextTask(documentFlowBO, request.getNextHandleUserId(), HANDLE_RESULT_ACCEPT);
        } else if (Objects.equals(request.getResult(), HANDLE_RESULT_REJECT)) {
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(documentFlowBO, UserContextHolder.getUserId(), PHASE_APPROVAL, HANDLE_RESULT_REJECT, request.getOpinion());
            documentFlowHandleManager.saveAllDocumentFlowHandle(Arrays.asList(documentFlowHandleBO));
            documentFlowBO.setPhase(PHASE_CONTENT_AUDIT);
            documentFlowServiceSupport.gotoNextTask(documentFlowBO, request.getNextHandleUserId(), HANDLE_RESULT_REJECT);
        }
        GetDocumentResponse documentByCode = ResultUtils.get(documentCodeRuleClient.getDocumentByCode(GetDocumentByCodeRequest.builder().code(documentFlowBO.getDocumentCode()).build()));
        documentFlowBO.setDocumentId(documentByCode.getDocumentId());
        documentFlowBO.setUpdateTime(now);
        documentFlowBO.setDocumentName(documentFlowBO.getDocumentName() + documentByCode.getFileExtension());
        int row = documentFlowManager.updateDocumentFlow(documentFlowBO);
        if (row > 0) {
            //发送消息
            //通过
            if (Objects.equals(request.getResult(), HANDLE_RESULT_ACCEPT)) {
                //发送消息

                //定义消息内容
                Message message = Message.builder()
                        .type(MessageTypeConstant.TYPE_FLOW)
                        .data(1)
                        .remark(getType() + "流程-发行")
                        .path(MessageTypeConstant.FLOW_LIST)
                        .build();
                sendMessage(message, request.getNextHandleUserId());
            } else {//拒绝通过
                //获取申请用户id  查找申请人员
                Long applyUserId = getApplyUserId(request.getDocumentFlowId(), PHASE_CONTENT_AUDIT);
                //发送消息

                //定义消息内容
                Message message = Message.builder()
                        .type(MessageTypeConstant.TYPE_FLOW)
                        .data(1)
                        .remark(getType() + "流程-审批不通过")
                        .path(MessageTypeConstant.FLOW_LIST)
                        .build();
                sendMessage(message, applyUserId);
            }
        }
        documentFlowBO.setDocumentName(buildName(documentFlowBO.getDocumentName(), documentByCode.getFileExtension()));
        documentFlowManager.updateDocumentFlow(documentFlowBO);
        return Result.success();
    }

    private String buildName(String name, String fileExtension) {
        if (name == null || ("").equals(name)) {
            return null;
        }
        if (name.contains(fileExtension) && name.substring(name.lastIndexOf('.'), name.length()).equals(fileExtension)) {
            return name;
        } else {
            return name + fileExtension;
        }
    }

    @Override
    public Result<?> getDocumentFlowPrintAndDrop(Long documentFlowId) {
        DocumentFlowBO documentFlowBO = documentFlowManager.getDocumentFlow(documentFlowId);
        if (Objects.isNull(documentFlowBO)) {
            return Result.fail("", "当前流程不存在！");
        }
        if (Objects.equals(DocumentFlowBatchTypeEnum.BATCH_PARENT.getCode(), documentFlowBO.getBatchType())) {
            List<DocumentFlowBO> documentFlowBOList = documentFlowManager.listDocumentFlow(DocumentFlowQuery.max()
                    .parentDocumentFlowId(documentFlowBO.getDocumentFlowId())
                    .batchType(DocumentFlowBatchTypeEnum.BATCH_SUBFILE.getCode())
                    .build());
            ListDocumentFlowBrorowAndPrintAndDropResponse listDocumentFlowBrorowAndPrintAndDropResponse = DocumentFlowConverter.toResponseList(documentFlowBO);
            listDocumentFlowBrorowAndPrintAndDropResponse.setDocumentFlowInfoList(DocumentFlowConverter.toResponseList(documentFlowBOList));
            buildFileExtension(listDocumentFlowBrorowAndPrintAndDropResponse);
            return Result.success(listDocumentFlowBrorowAndPrintAndDropResponse);
        } else {
            ListDocumentFlowBrorowAndPrintAndDropResponse listDocumentFlowBrorowAndPrintAndDropResponse = DocumentFlowConverter.toResponseList(documentFlowBO);
            listDocumentFlowBrorowAndPrintAndDropResponse.setDocumentFlowInfoList(DocumentFlowConverter.toResponseList(Collections.singleton(documentFlowBO)));
            buildFileExtension(listDocumentFlowBrorowAndPrintAndDropResponse);
            return Result.success(listDocumentFlowBrorowAndPrintAndDropResponse);
        }
    }

    private void buildFileExtension(ListDocumentFlowBrorowAndPrintAndDropResponse response) {
        List<ListDocumentFlowBrorowAndPrintAndDropResponse.DocumentFlowInfo> documentFlowInfoList = response.getDocumentFlowInfoList();
        documentClient.buildByDocument(documentFlowInfoList,
                documentFlowInfoList.stream().map(ListDocumentFlowBrorowAndPrintAndDropResponse.DocumentFlowInfo::getDocumentId).collect(Collectors.toSet()),
                ListDocumentFlowBrorowAndPrintAndDropResponse.DocumentFlowInfo::getDocumentId,
                (documentFlowInfo, document) -> documentFlowInfo.setFileExtension(document.getFileExtension()));
    }

    private DocumentReleaseBO buildDocumentReleaseBO(DocumentFlowBO documentFlowBO, Long receiveId, Integer receiveType,
                                                     LocalDate effectDate, LocalDate failureDate) {
        LocalDateTime now = LocalDateTime.now();
        return DocumentReleaseBO.builder()
                .receiveId(receiveId)
                .receiveType(receiveType)
                .status(STATUS_RELEASE)
                .permission(DocumentPermissions.addPermission(VISIBLE, PREVIEW))
                .documentId(documentFlowBO.getDocumentId())
                .documentCode(documentFlowBO.getDocumentCode())
                .documentName(documentFlowBO.getDocumentName())
                .documentVersion(documentFlowBO.getDocumentVersion())
                .documentFlowId(documentFlowBO.getDocumentFlowId())
                .flowType(documentFlowBO.getFlowType())
                .documentLevel(documentFlowBO.getDocumentLevel())
                .documentProperty(documentFlowBO.getDocumentProperty())
                .tenantId(0L)
                .createUserId(UserContextHolder.getUserId())
                .createTime(now)
                .updateTime(now)
                .effectDate(effectDate)
                .failureDate(failureDate)
                .build();
    }


    /**
     * 获取申请用户id
     * @param documentFlowId
     * @return
     */
    protected Long getApplyUserId(Long documentFlowId, String phase) {
        List<DocumentFlowHandleBO> documentFlowHandleBOS = documentFlowHandleManager.listDocumentFlowHandle(DocumentFlowHandleQuery.builder()
                .documentFlowId(documentFlowId)
                .phase(phase)
                .build());
        DocumentFlowHandleBO documentFlowHandleBO1 = documentFlowHandleBOS.get(0);
        return documentFlowHandleBO1.getHandleUserId();
    }

    /**
     * 发送信息
     * @param message
     * @param toId
     */
    protected void sendMessage(Message message, Long toId) {
        messagePushClient.send(MessagePushRequest.builder()
                .data(JsonUtils.toJson(message).getBytes())
                .dataType(0)
                .expiredSeconds(0L)
                .toId(toId)
                .offlineFlag(true).build());
    }

    protected DocumentFlowBorrowAndPrintAndDropBO buildDocumentFlowBorrowAndPrintAndDropList(List<DocumentFlowBorrowAndPrintAndDropBO> documentFlowBorrowAndPrintAndDropBOList, Integer flowType) {
        Objects.requireNonNull(documentFlowBorrowAndPrintAndDropBOList);
        DocumentFlowBorrowAndPrintAndDropBO parentFlow;
        if (documentFlowBorrowAndPrintAndDropBOList.stream().allMatch(e -> e.getBatchType().equals(DocumentFlowBatchTypeEnum.UNBATCH.getCode()))) {
            documentFlowBorrowAndPrintAndDropBOList.forEach(e -> buildDocumentFLowBorrowAndPrintAndDropBO(e, flowType, DocumentFlowBatchTypeEnum.UNBATCH.getCode(), null));
            parentFlow = documentFlowBorrowAndPrintAndDropBOList.get(0);
        } else {
            parentFlow = BeanUtilsEx.copyProperties(documentFlowBorrowAndPrintAndDropBOList.get(0), DocumentFlowBorrowAndPrintAndDropBO::new);
            buildDocumentFLowBorrowAndPrintAndDropBO(parentFlow, flowType, DocumentFlowBatchTypeEnum.BATCH_PARENT.getCode(), null);
            parentFlow.setDocumentName(null);
            documentFlowBorrowAndPrintAndDropBOList.forEach(e -> {
                String documentName = Objects.isNull(parentFlow.getDocumentName()) ? "" : parentFlow.getDocumentName() + "，";
                parentFlow.setDocumentName(documentName.length() > 190 ? documentName.substring(0, 190) + "......" : documentName + e.getDocumentName());
                buildDocumentFLowBorrowAndPrintAndDropBO(e, flowType, DocumentFlowBatchTypeEnum.BATCH_SUBFILE.getCode(), parentFlow.getDocumentFlowId());
            });
            documentFlowBorrowAndPrintAndDropBOList.add(parentFlow);
        }
        DocumentFlowHandleBO.build(parentFlow, UserContextHolder.getUserId(), PHASE_APPLY, HANDLE_RESULT_ACCEPT, parentFlow.getReason());
        return parentFlow;
    }

    private void buildDocumentFLowBorrowAndPrintAndDropBO(DocumentFlowBorrowAndPrintAndDropBO documentFlowBorrowAndPrintAndDropBO, Integer flowType, Integer batchType, Long parentDocumentFlowId) {
        LocalDateTime now = LocalDateTime.now();
        documentFlowBorrowAndPrintAndDropBO.setDocumentFlowId(gidService.generate());
        documentFlowBorrowAndPrintAndDropBO.setFlowType(flowType);
        documentFlowBorrowAndPrintAndDropBO.setPhase(PHASE_CONTENT_AUDIT);
        documentFlowBorrowAndPrintAndDropBO.setBatchType(batchType);
        documentFlowBorrowAndPrintAndDropBO.setParentDocumentFlowId(parentDocumentFlowId);
        if (Objects.isNull(documentFlowBorrowAndPrintAndDropBO.getDocumentId())) {
            documentFlowBorrowAndPrintAndDropBO.setDocumentId(0L);
        }
        documentFlowBorrowAndPrintAndDropBO.setTenantId(UserContextHolder.getTenantId());
        documentFlowBorrowAndPrintAndDropBO.setCreateUserId(UserContextHolder.getUserId());
        documentFlowBorrowAndPrintAndDropBO.setCreateUserName(UserContextHolder.getUserName());
        documentFlowBorrowAndPrintAndDropBO.setCreateUserGroupId(UserContextHolder.getUserGroupId());
        documentFlowBorrowAndPrintAndDropBO.setCreateUserGroupName(UserContextHolder.getUserGroupName());
        documentFlowBorrowAndPrintAndDropBO.setCreateTime(now);
        documentFlowBorrowAndPrintAndDropBO.setUpdateTime(now);
        documentFlowBorrowAndPrintAndDropBO.setTrainFlag(false);
    }

    protected Result<Triple<List<DocumentFlowBO>, List<Long>, List<Long>>> saveDocumentReleaseList(ReleaseDocumentFlowNewAndModifyRequest request, DocumentFlowBO documentFlowBO, Integer batchType) {
        DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(documentFlowBO, UserContextHolder.getUserId(), PHASE_RELEASE, HANDLE_RESULT_ACCEPT, request.getOpinion());
        documentFlowHandleManager.saveAllDocumentFlowHandle(Collections.singletonList(documentFlowHandleBO));
        documentFlowServiceSupport.finishLastTask(documentFlowBO);
        List<DocumentFlowBO> documentFlowList = new ArrayList<>();
        if (batchType.equals(DocumentFlowBatchTypeEnum.BATCH_PARENT.getCode())) {
            documentFlowList = documentFlowManager.listDocumentFlow(DocumentFlowQuery
                    .max()
                    .batchType(DocumentFlowBatchTypeEnum.BATCH_SUBFILE.getCode())
                    .parentDocumentFlowId(documentFlowBO.getDocumentFlowId())
                    .build());
            Objects.requireNonNull(documentFlowList);
        }
        if (batchType.equals(DocumentFlowBatchTypeEnum.UNBATCH.getCode())) {
            documentFlowList.add(documentFlowBO);
        }
        List<Long> receiveUserGroupIdList = request.getReceiveUserGroupIdList();
        List<Long> receiveUserIdList = buildUserIdCollection(request.getReceiveUserIdList(), receiveUserGroupIdList);
        List<DocumentReleaseBO> documentReleaseBOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(receiveUserIdList)) {
            for (DocumentFlowBO e : documentFlowList) {
                for (Long receiveUserId : receiveUserIdList) {
                    documentReleaseBOList.add(buildDocumentReleaseBO(e, receiveUserId, RECEIVE_TYPE_USER, request.getEffectDate(), request.getFailureDate()));
                }
            }
        }
        if (!CollectionUtils.isEmpty(receiveUserGroupIdList)) {
            for (DocumentFlowBO e : documentFlowList) {
                for (Long receiveUserGroupId : receiveUserGroupIdList) {
                    documentReleaseBOList.add(buildDocumentReleaseBO(e, receiveUserGroupId, RECEIVE_TYPE_USER_GROUP, request.getEffectDate(), request.getFailureDate()));
                }
            }
        }
        int row;
        if (documentFlowBO.getFlowType().equals(DocumentFlowConstants.FLOW_TYPE_DROP)) {
            List<DocumentReleaseBO> documentReleaseBOList1 = new ArrayList<>();
            List<SaveDocumentRequest> documentRequestList = new ArrayList<>();
            for (DocumentFlowBO flowBO : documentFlowList) {
                documentRequestList.add(SaveDocumentRequest
                        .builder()
                        .documentId(flowBO.getDocumentId())
                        .documentName(flowBO.getDocumentName())
                        .version(flowBO.getDocumentVersion())
                        .repositoryId(DocumentDefaultRepositoryEnum.OBSOLETE_REPOSITORY.getCode())
                        .latestVersionFlag(1)
                        .build());
                documentReleaseBOList1.add(DocumentReleaseBO.builder()
                        .documentCode(flowBO.getDocumentCode())
                        .documentVersion(flowBO.getDocumentVersion())
                        .status(DocumentReleaseStatusEnum.OBSOLETE.getCode())
                        .updateTime(LocalDateTime.now())
                        .build());
            }
            row = documentReleaseManager.updateAllDocumentRelease(documentReleaseBOList1);
            documentClient.updateAllDocument(documentRequestList);
        } else {
            row = documentReleaseManager.saveAllDocumentRelease(documentReleaseBOList);
        }
        if (row > 0) {
            return Result.success(new Triple(documentFlowList, receiveUserIdList, receiveUserGroupIdList));
        }
        return Result.fail();
    }

    protected List<Long> buildUserIdCollection(List<Long> userIdList, List<Long> userGroupIdList) {
        if (!CollectionUtils.isEmpty(userGroupIdList) && !CollectionUtils.isEmpty(userIdList)) {
            Set<Long> ids = ResultUtils.get(userClient.listUserByUserGroup(ListUserGroupByIdsRequest.builder()
                            .groupIds(userGroupIdList).build()))
                    .stream().map(UserDTO::getUserId).collect(Collectors.toSet());
            return userIdList.stream().filter(e -> !ids.contains(e)).collect(toList());
        }
        return userIdList;
    }

    protected Set<Long> buildMessageReceiveUserIdCollection(List<Long> userIdList, List<Long> userGroupIdList) {
        Set<Long> userIds = new HashSet<>();
        //获取需要发送信息的用户
        if (!CollectionUtils.isEmpty(userIdList)) {
            userIds.addAll(userIdList);
        }
        if (!CollectionUtils.isEmpty(userGroupIdList)) {
            Result<Collection<Long>> collectionResult = userClient.listUserIdByUserGroupId(userGroupIdList);
            if (collectionResult.wasSuccess()) {
                if (!CollectionUtils.isEmpty(collectionResult.getData())) {
                    userIds.addAll(collectionResult.getData());
                }
            }
        }
        return userIds;
    }
}
